package com.shycloud.mido.common.security.mobile;

import com.shycloud.mido.common.core.constant.CommonConstants;
import com.shycloud.mido.common.core.exception.ValidateCodeException;
import com.shycloud.mido.common.security.service.ShyUserDetailsService;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsChecker;

/**
 * @author npc
 * @date 2018/8/5
 * 手机登录校验逻辑
 * 验证码登录、社交登录
 */
@Slf4j
@AllArgsConstructor
public class MobileAuthenticationProvider implements AuthenticationProvider {

	//private MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
	//private UserDetailsChecker detailsChecker = new ShyPreAuthenticationChecks();

	private MessageSourceAccessor messages;

	private UserDetailsChecker detailsChecker;

	private final RedisTemplate redisTemplate;

	@Getter
	@Setter
	private ShyUserDetailsService userDetailsService;

	@Override
	@SneakyThrows
	public Authentication authenticate(Authentication authentication) {

		MobileAuthenticationToken mobileAuthenticationToken = (MobileAuthenticationToken) authentication;

		String principal = mobileAuthenticationToken.getPrincipal().toString();

		String[] principalAfter = principal.split(",");

		//两个参数是手机端验证码登录, 四个参数是小程序验证码登录
		//根据参数列表长度进行重载
		if (principalAfter.length == 2 || principalAfter.length == 4) {

			String code = (String) redisTemplate.opsForValue().get(CommonConstants.DEFAULT_CODE_KEY + principalAfter[0]);

			if (code == null) {
				throw new ValidateCodeException("验证码已过期");
			}

			//校验验证码
			if (!principalAfter[1].equals(code)) {
				throw new ValidateCodeException("验证码不正确");
			}

		}

		UserDetails userDetails = userDetailsService.loadUserByMobile(principalAfter[0], principalAfter[1]);

		if (principalAfter.length == 4) {
			userDetails = userDetailsService.loadUserByMobile(principalAfter[0], principalAfter[3]);
		}

		if (userDetails == null) {
			log.debug("Authentication failed: no credentials provided");

			throw new BadCredentialsException(messages.getMessage(
					"AbstractUserDetailsAuthenticationProvider.noopBindAccount",
					"Noop Bind Account"));
		}

		// 检查账号状态
		detailsChecker.check(userDetails);

		MobileAuthenticationToken authenticationToken = new MobileAuthenticationToken(userDetails, userDetails.getAuthorities());
		authenticationToken.setDetails(mobileAuthenticationToken.getDetails());

		//TODO 删除redis里的 KEY
		redisTemplate.delete(CommonConstants.DEFAULT_CODE_KEY + principalAfter[0]);

 		return authenticationToken;
	}

	@Override
	public boolean supports(Class<?> authentication) {
		return MobileAuthenticationToken.class.isAssignableFrom(authentication);
	}
}